const jwt = require("jsonwebtoken");
const expressJWT = require("express-jwt");
const { tokenSecret } = require("@conf/config");

class JWT {
  constructor(token, userInfo) {
    this.token = token;
    this.userInfo = userInfo || {};
  }

  sign(id, phone) {
    return jwt.sign({ id, phone }, tokenSecret, {
      algorithm: "HS256", // 默认 HS256
      // expiresIn: "7d", // 过期时间，秒或描述时间跨度 zeit / ms 的字符串
      expiresIn: "60000",
      // notBefore: 120,
      // audience: "", // 观众
      // issuer: "", // 发行者
      // jwtid: "", // JWT ID
      // subject: "", // 主题
      // noTimestamp: "",
      // header: "",
      // keyid: "",
      // mutatePayload: "",
    });
  }

  verify(token) {
    return jwt.verify(token, tokenSecret, {
      algorithms: ["HS256"],
      // audience: "", // 验证观众
      // issuer: "", // 验证发行者
      // ignoreExpiration: false, // 是否忽略验证过期时间
      // ignoreNotBefore: false,
      // maxAge: 120, // 默认 120ms
      // clockTimestamp: "",
      // nonce: "",
    });
  }
}

class ExpressJWT {
  constructor(path) {
    this.path = path;
  }

  sign() {
    expressJWT({
      secret, // 密钥 或 PublicKey
      algorithms: ['HS256'], // 使用第三方库作为密钥时，需指定该参数来防止潜在降级攻击
      requestProperty: "auth", // 解析结果赋值位置，默认 req.user
      credentialsRequired: false, // 当接口允许不带 Token 和带 Token 两种状态的访问时（比如文章详情登录后判断点赞），可以通过 credentialsRequired: false 来对无 Token 请求不进行解析和抛出异常。

       // 默认情况下，express-jwt 是从请求 Headers 的 Authorization 字段来获取 Token 并解析。
      // 通过 getToken 也可以自定义一些解析逻辑，比如使用其他 Header 字段，自定义抛出异常等：
      getToken: function fromHeaderOrQuerystring (req) {
        if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
          return req.headers.authorization.split(' ')[1]
        } else if (req.query && req.query.token) {
          return req.query.token
        }
        return null
      },


      // 作废 Token
  //     // 在 JWT 机制中，由于 Token 通常不进行存储，如果想作废某一条 Token，一般都是通过被动的方式。
      // 常用的方式是建立某个字段的黑名单（比如 TokenId），对所有 Token 进行过滤，express-jwt 专门提供了回调来处理这种情况：
      isRevoked: (req, payload, done) => {
        let issuer = payload.iss
        let tokenId = payload.jti

        // blacklist 黑名单
        blacklist.getRevokedToken(issuer, tokenId, function(err, token){
          if (err) { return done(err) }
          return done(null, !!token)  // 第二个参数为 true 则不通过
        })
      }
    }).unless({
      path: this.path, // 指定不经过 Token 解析的路径
    });
  }

  // 获取解析内容
  // 当收到带 Token 的请求，如果解析成功，就可以在路由回调里通过 req.user 来访问：
  // req.user 实际就是 JWT 的 payload 部分：

// {
//   _id: '5dbbc7daaf7dfe003680ba39',
//   admin: true,
//   iat: 1572587484,
//   exp: 1573192284
// }
  verify(data) {

  }
}

module.exports = {
  JWT,
  ExpressJWT,
};
